package com.zxbit.uangstore.network;

import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import com.zxbit.uangstore.utils.DebugLog;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;


public class RetrofitManager {
    private static final int DEFAULT_TIME_OUT = 30;
    private static final int DEFAULT_READ_TIME_OUT = 60;
    private static final int DEFAULT_WRITE_TIME_OUT = 30;

    private static final Map<String, Retrofit> retrofitMap = new HashMap();
    private final OkHttpClient okHttpClient;

    public RetrofitManager() {
        OkHttpClient.Builder okBuilder = new OkHttpClient.Builder();

        okBuilder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);
        okBuilder.readTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);
        okBuilder.writeTimeout(DEFAULT_WRITE_TIME_OUT, TimeUnit.SECONDS);
        okBuilder.addNetworkInterceptor(new LogInterceptor());
        okHttpClient = okBuilder.build();
    }

    private Retrofit generateRetrofit(String baseUrl) {
        if (baseUrl == null || "".equals(baseUrl)) {
            throw new RuntimeException("base url is null");
        }
        Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
        return retrofitBuilder.client(okHttpClient)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(baseUrl)
                .build();
    }

    private static class SongletonHolder {
        static RetrofitManager mInstance = new RetrofitManager();
    }

    public static RetrofitManager getInstance() {
        return SongletonHolder.mInstance;
    }

    public <T> T createApiService(String baseUrl, Class<T> apiService) {
        if (baseUrl == null || "".equals(baseUrl)) {
            throw new RuntimeException("baseurl  is null");
        }

        Retrofit retrofit = retrofitMap.get(baseUrl);
        if (retrofit == null) {
            retrofit = generateRetrofit(baseUrl);
            retrofitMap.put(baseUrl, retrofit);
        }
        return retrofit.create(apiService);
    }


    public ApiService getApiService() {
        return createApiService(Urls.BASE_URL, ApiService.class);
    }

    public void clearCacheRetroFit() {
        retrofitMap.clear();
    }


    public static class LogInterceptor implements Interceptor {

        private static final String TAG = LogInterceptor.class.getSimpleName();

        @Override
        public Response intercept(Chain chain) throws IOException {
            Response response = chain.proceed(chain.request());
            if (response != null && response.body() != null) {

                String bodyInfo = response.toString();
                MediaType mediaType = response.body().contentType();
                DebugLog.i(TAG, bodyInfo + "||mediaType:" + mediaType);
            }

            return response;
        }
    }

    /**
     * 通过okhttpClient来设置证书
     *
     * @param clientBuilder OKhttpClient.builder
     * @param certificates  读取证书的InputStream
     */
    public void setCertificates(OkHttpClient.Builder clientBuilder, InputStream... certificates) {
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            int index = 0;
            for (InputStream certificate : certificates) {
                String certificateAlias = Integer.toString(index++);
                keyStore.setCertificateEntry(certificateAlias, certificateFactory
                        .generateCertificate(certificate));
                try {
                    if (certificate != null)
                        certificate.close();
                } catch (IOException e) {
                }
            }
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                    TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
            if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
                throw new IllegalStateException("Unexpected default trust managers:"
                        + Arrays.toString(trustManagers));
            }
            X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
            clientBuilder.sslSocketFactory(sslSocketFactory, trustManager);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
